﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Sprout.Core.Extensions
{
    /// <summary>
    /// 时间的扩展方法
    /// </summary>
    public static class DateExtensions
    {
        /// <summary>
        /// 把时间转为unix时间戳
        /// </summary>
        /// <param name="dateTime">时间</param>
        /// <returns></returns>
        public static long ToUnixTime(this DateTime dateTime)
        {
            DateTimeOffset dateTimeOffset = new DateTimeOffset(dateTime);
            return dateTimeOffset.ToUnixTimeSeconds();
        }

        /// <summary>
        /// 把时间戳转为时间
        /// </summary>
        /// <param name="unixTime">时间戳</param>
        /// <returns></returns>
        public static DateTime ToDateTime(this long unixTime)
        {
            DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(unixTime);
            return dateTimeOffset.LocalDateTime;
        }

        /// <summary>
        /// 时间戳转为UTC时间
        /// </summary>
        /// <param name="unixTime">时间戳</param>
        /// <returns></returns>
        public static DateTime ToUTCDateTime(this long unixTime)
        {
            DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(unixTime);
            return dateTimeOffset.UtcDateTime;
        }

        /// <summary>
        /// 时间戳转UTC时间
        /// </summary>
        /// <param name="dateTime">当前时间戳</param>
        /// <returns></returns>
        public static DateTime ConvertFromDateTimeOffset(this DateTimeOffset dateTime)
        {
            if (dateTime.Offset.Equals(TimeSpan.Zero))
                return dateTime.UtcDateTime;
            else if (dateTime.Offset.Equals(TimeZoneInfo.Local.GetUtcOffset(dateTime.DateTime)))
                return DateTime.SpecifyKind(dateTime.DateTime, DateTimeKind.Local);
            else
                return dateTime.DateTime;
        }

        /// <summary>
        /// 当前时间戳是否大于目标时间戳
        /// </summary>
        /// <param name="sourceTime">当前时间戳</param>
        /// <param name="targetTime">目标时间戳</param>
        /// <returns></returns>
        public static bool IsMoreTargetUnix(this long sourceTime, long targetTime)
        {
            return sourceTime > targetTime;
        }

        /// <summary>
        /// 当前时间戳是否小于目标时间戳
        /// </summary>
        /// <param name="sourceTime">当前时间戳</param>
        /// <param name="targetTime">目标时间戳</param>
        /// <returns></returns>
        public static bool IsLessTargetUnix(this long sourceTime, long targetTime)
        {
            return sourceTime < targetTime;
        }

        /// <summary>
        /// 当前时间戳是否等于目标时间戳
        /// </summary>
        /// <param name="sourceTime">当前时间戳</param>
        /// <param name="targetTime">目标时间戳</param>
        /// <returns></returns>
        public static bool IsEquleTargetUnix(this long sourceTime, long targetTime)
        {
            return sourceTime == targetTime;
        }

        /// <summary>
        /// 获取本周星期日
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static DateTime ToWeekLastDate(this DateTime dateTime)
        {
            var dayOfWeek = dateTime.DayOfWeek;
            if (dayOfWeek == DayOfWeek.Sunday)
            {
                return dateTime.Date;
            }
            else
            {
                return dateTime.Date.AddDays(7 - (int)dayOfWeek);
            }
        }

        /// <summary>
        /// 取得某月的第一天
        /// </summary>
        /// <param name="datetime">要取得月份第一天的时间</param>
        /// <returns></returns>
        public static DateTime FirstDayOfMonth(this DateTime datetime)
        {
            return datetime.AddDays(1 - datetime.Day);
        }

        //// <summary>
        /// 取得某月的最后一天
        /// </summary>
        /// <param name="datetime">要取得月份最后一天的时间</param>
        /// <returns></returns>
        public static DateTime LastDayOfMonth(this DateTime datetime)
        {
            return datetime.AddDays(1 - datetime.Day).AddMonths(1).AddDays(-1);
        }

        /// <summary>
        /// 获取客户端时间
        /// </summary>
        /// <param name="datetime"></param>
        /// <param name="timeZone"></param>
        /// <returns></returns>
        public static DateTime ToLocalTime(this DateTime datetime, int timeZone)
        {
            if (datetime.Kind == DateTimeKind.Utc)
            {
                return datetime.AddHours(timeZone);
            }
            else
            {
                return datetime.AddHours(timeZone - TimeZone());
            }
        }

        /// <summary>
        /// unix时间差转本地时间
        /// </summary>
        /// <param name="unixTime">unix时间戳</param>
        /// <param name="timeZone">时区</param>
        /// <returns></returns>
        public static DateTime ToLocalTime(this long unixTime, int timeZone)
        {
            return unixTime.ToDateTime().ToLocalTime(timeZone);
        }

        /// <summary>
        /// 获取客户端 年月日
        /// </summary>
        /// <param name="datetime">时间</param>
        /// <param name="timeZone">时区</param>
        /// <returns></returns>
        public static DateTime ToDate(this DateTime datetime, int timeZone)
        {
            if (datetime.Kind == DateTimeKind.Utc)
            {
                return datetime.ToLocalTime(timeZone).Date.AddHours(-timeZone);
            }
            else
            {
                return datetime.ToLocalTime(timeZone).Date.AddHours(TimeZone() - timeZone);
            }
        }

        /// <summary>
        /// 获取客户端 年月日时间缀
        /// </summary>
        /// <param name="datetime"></param>
        /// <param name="timeZone"></param>
        /// <returns></returns>
        public static long ToDateUnixTime(this DateTime datetime, int timeZone)
        {
            return datetime.ToDate(timeZone).ToUnixTime();
        }

        /// <summary>
        /// unix时间差转只带年月日的时间戳
        /// </summary>
        /// <param name="unixTime">unix时间戳</param>
        /// <param name="timeZone">时区</param>
        /// <returns></returns>
        public static long ToDateUnixTime(this long unixTime, int timeZone)
        {
            return unixTime.ToDateTime().ToDateUnixTime(timeZone);
        }

        /// <summary>
        /// 根据客户端时间获取服务器时间
        /// </summary>
        /// <param name="datetime">转出的客户端时间</param>
        /// <param name="timeZone">时区</param>
        /// <returns></returns>
        public static DateTime ToServiceTime(this DateTime datetime, int timeZone)
        {
            if (datetime.Kind == DateTimeKind.Utc)
            {
                return datetime.AddHours(-timeZone);
            }
            else
            {
                return datetime.AddHours(TimeZone() - timeZone);
            }
        }

        /// <summary>
        /// 根据客户端时间获取真实时间缀
        /// </summary>
        /// <param name="datetime">转出的客户端时间</param>
        /// <param name="timeZone">时区</param>
        /// <returns></returns>
        public static long ToServiceUnixTime(this DateTime datetime, int timeZone)
        {
            return datetime.ToServiceTime(timeZone).ToUnixTime();
        }

        /// <summary>
        /// 获取服务器时区
        /// </summary>
        /// <returns></returns>
        public static int TimeZone()
        {
            int timeZone = Convert.ToInt32(DateTime.Now.ToString("%z"));
            return timeZone;
        }
    }
}
